package org.ch02.test09.demo04;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

/**
 * @author ZQX
 * @date 2025-03-24
 */
public class BeanUtil {
    /**
     * 1、设置何意对象的属性值
     *
     * @param bean         Bean对象
     * @param propertyName 属性名称
     * @param value        属性值
     */
    public static void setProperty(Object bean, String propertyName, Object value) {
        try {
            // 实例化 PropertyDescriptor 对象 - 指向某个类的某个属性
            PropertyDescriptor propertyDescriptor = new
                    PropertyDescriptor(propertyName,
                    bean.getClass());

            // 获取属性对象的 setter 方法
            Method writeMethod = propertyDescriptor.getWriteMethod();

            // 调用方法
            writeMethod.invoke(bean, value);
        } catch (IntrospectionException e) {
            throw new RuntimeException("属性不存在", e);
        } catch (Exception e) {
            throw new RuntimeException("初始化失败", e);
        }
    }

    /**
     * 2、获取任意对象的属性值
     *
     * @param bean         Bean对象
     * @param propertyName 属性名称
     * @return 属性值
     */
    public static Object getProperty(Object bean, String propertyName) {

        try {
            // 实例化 PropertyDescriptor 对象 - 指向某个类的某个属性
            PropertyDescriptor propertyDescriptor = new
                    PropertyDescriptor(propertyName,
                    bean.getClass());

            // 获取 getter 方法，并调用
            return propertyDescriptor.getReadMethod().invoke(bean);
        } catch (IntrospectionException e) {
            throw new RuntimeException("属性不存在", e);
        } catch (Exception e) {
            throw new RuntimeException("获取属性值失败", e);
        }
    }

    /**
     * 3、复制某个对象的属性值到另一个对象中
     *
     * @param sourceBean 源 Bean 对象
     * @param targetBean 目标 Bean 对象
     */
    public static void copyProperties(Object sourceBean, Object targetBean) {
        try {
            // 获取 Bean 对象的 BeanInfo 对象
            BeanInfo sourceBeanInfo = Introspector.getBeanInfo(sourceBean.getClass(), Object.class);

            // 获取 Bean 对象中的所有 属性
            PropertyDescriptor[] propertyDescriptors = sourceBeanInfo.getPropertyDescriptors();

            // 循环遍历所有的属性
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                // 获取属性名称
                String propertyName = propertyDescriptor.getName();

                // 获取属性值
                Object propertyValue = getProperty(sourceBean, propertyName);

                // 给目标对象赋值
                setProperty(targetBean, propertyName, propertyValue);
            }
        } catch (IntrospectionException e) {
            throw new RuntimeException(e);
        }
    }
}
